export default function CanvasLine(option) {
  let defaultOption = {
    table: null, // 表格容器或其他需要划线的容器，只能是dom对象
    lineTypes: [{ selector: '.dot', lineColor: 'red', lineWidth: 1 }], // 表格中需要进行连线的线的种类
    visible: true, // 是否显示折线
  }
  Object.assign(this, defaultOption, option);

  this.init();
}

Object.assign(CanvasLine.prototype, {
  init() {
    this.tableParent = this.table.parentNode;
    if (getComputedStyle(this.tableParent).position == 'static') this.tableParent.style.position = 'relative';
    if (getComputedStyle(this.table).position == 'static') this.table.style.position = 'relative';
    this.canvas = document.createElement('canvas');
    Object.assign(this.canvas.style, {
      position: 'absolute',
      pointerEvents: 'none',
      left: 0,
      top: 0,
      visibility: this.visible ? 'visible' : 'hidden',
    });
    this.tableParent.append(this.canvas);
    this.ctx = this.canvas.getContext('2d');
    this.resizeHandler = function () {
      this.setCanvas();
      this.draw();
    }.bind(this);
    window.addEventListener('resize', this.resizeHandler);
    this.resizeHandler();
  },
  setCanvas() {
    this.canvas.width = this.table.offsetWidth;
    this.canvas.height = this.table.offsetHeight;
    Object.assign(this.canvas.style, {
      left: this.table.offsetLeft + 'px',
      top: this.table.offsetTop + 'px',
    });
  },
  show() {
    this.visible = true;
    this.canvas.style.visibility = 'visible';
  },
  hide() {
    this.visible = false;
    this.canvas.style.visibility = 'hidden';
  },
  toggle() {
    this.visible ? this.hide() : this.show();
  },
  draw() {
    this.ctx.clearRect(0, 0, Infinity, Infinity);
    this.lineTypes.forEach(obj => {
      let { selector, lineColor, lineWidth } = { lineColor: '#000', lineWidth: 1, ...obj };
      let tds = this.table.querySelectorAll(selector);
      let getOffset = (el, key) => {
        let value = 0;
        let computeValue = el => {
          if (el.offsetParent == this.table) {
            return value += el[key];
          } else {
            value += el[key];
            return computeValue(el.offsetParent);
          }
        };
        return computeValue(el);
      };
      this.ctx.lineWidth = lineWidth;
      this.ctx.strokeStyle = lineColor;
      tds.forEach((td, i, tds) => {
        let tdWidth = td.center ? td.center.w : td.offsetWidth;
        let tdHeight = td.center ? td.center.h : td.offsetHeight;
        let start = td.center || {
          x: getOffset(td, 'offsetLeft') + tdWidth / 2,
          y: getOffset(td, 'offsetTop') + tdHeight / 2,
          w: tdWidth,
          h: tdHeight,
        };
        td.center && delete td.center;

        let next = tds[i + 1];
        if (!next) return;
        let nextWidth = next.offsetWidth;
        let nextHeight = next.offsetHeight;
        let end = next.center = {
          x: getOffset(next, 'offsetLeft') + nextWidth / 2,
          y: getOffset(next, 'offsetTop') + nextHeight / 2,
          w: nextWidth,
          h: nextHeight,
        };

        let startR = Math.min(start.w, start.h) / 2;
        let endR = Math.min(end.w, end.h) / 2;
        let rad = Math.atan((end.x - start.x) / (end.y - start.y));
        let xRate = Math.sin(rad);
        let yRate = Math.cos(rad);

        this.ctx.beginPath();
        let startX = Math.ceil(start.x + startR * xRate);
        let startY = Math.ceil(start.y + startR * yRate);
        this.ctx.moveTo(startX, startY);
        let endX = Math.ceil(end.x - endR * xRate);
        let endY = Math.ceil(end.y - endR * yRate);
        this.ctx.lineTo(endX, endY);
        this.ctx.closePath();
        this.ctx.stroke();
      });
    });
  },
  destroy() {
    this.canvas.remove();
    window.removeEventListener('resize', this.resizeHandler);
  },
})